/*
 * Copyright 2002-2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.beans.factory;

import org.springframework.beans.BeansException;
import org.springframework.core.ResolvableType;
import org.springframework.lang.Nullable;

/**
 *
 * BeanFactory总结一句话：
 * 			利用原型模式返回Prototype类型的bean，而单例模式返回单例bean
 *
 *
 *
 *BeanFactory(Bean的工厂)：
 *  什么是BeanFactory(Bean的工厂)?
 *  	1.spring的整个框架其实就是工厂里面造东西的流程，所以只要我们分析清楚这个BeanFactory(Bean的工厂)干了什么活，那么spring清楚了
 * 		2.既然名字起了叫BeanFactory(Bean的工厂)，那么自热而然就得是一个工厂，既然是一个工厂就得造东西
 *  	3.那么BeanFactory(Bean的工厂)造的都是些什么东西？所以有工厂无外乎就是简单工厂，抽象工厂，工厂方法
 *  	4.那么BeanFactory(Bean的工厂)又是个什么工厂？
 *  	 4.1 BeanFactory(Bean的工厂)这个工厂最重要的就是造组件，然后返回的是一个T的对象，所以这个BeanFactory(Bean的工厂)是一个工厂方法模式
 *		 4.2 因为BeanFactory(Bean的工厂)这个工厂产品线单一，它只造bean,但它不是简单工厂模式，因为spring在底层不是一个ifelse就搞定的，它底层还很复杂，所以它只提供了一个工厂方法
 *		 4.2 所以它使用工厂方法模式，给我们造组件
 *		5.首先BeanFactory(Bean的工厂)里面下设三大工厂：俗称分厂
 *			5.1.HierarchicalBeanFactory, 5.2.ListableBeanFacotory 5.3 AutowireCapableBeanFactory
 *			5.4 在spring的里面BeanFactory(Bean的工厂)下还有抽象工厂，但这些抽象工厂都没有创建产品的方法，
 *			相当于一个产品线，做一个产品，它的一个抽象工厂只是相当于对工厂的功能增强，跟产品没关系，所以它的这些抽象工厂不成立
 *			5.5 抽象工厂想要成立就是：有总厂（BeanFactory） 总厂下的分厂要造产品的，对产品的接口会有其他规划
 *      6. 所有从BeanFactory(Bean的工厂)类上来看，还是一个工厂方法模式
 *      7.首先它有一个定义父子工厂的接口（HierarchicalBeanFactory）也就是父子容器
 *
 *
 *     8.一个（BeanDefinitionRegistry）档案馆里面没有任何制造好的bean,只有图纸，那这些制造好的组件这才是ioc容器，就是谁如果把制造好的东西存起来了，谁就是ioc容器
 *     在底层只要谁把所有的这个单例对象给存起来了，谁就是那个ioc容器，那既然是容器，它还要存东西，那它在底层肯定是个集合接口（Map）
 *     如果是一个list接口，这些组件还要用名字去拿，还可能要用类型去拿就不太行了，若是set的就更加不行了，所以唯有Map才能实现
 *     	所以就来寻找是哪个map类型的IOC容器把这个存组件的事给干了？
 *
 *
 *     	9.先看看（BeanDefinition）档案馆是如何工作的
 *     		9.1.注册bean的定义信息，是来实现BeanDefinitionRegistry接口的，
 * 			9.2.BeanDefinition（bean的定义信息），这个BeanDefinition（bean的定义信息）
 * 			9.3.存在了BeanDefinitionRegistry（bean定义中心）里面,
 * 			9.4.正好BeanDefinition（bean的定义信息，也既档案馆）实现了BeanDefinitionRegistry（bean定义中心）
 * 			9.5.那么也自然要做的事情就是要编写人家的方法，其中有一个叫void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)注册bean的定义信息的方法
 * 			9.6.所以BeanDefinition（bean的定义信息，也既档案馆）底层就会有这个registerBeanDefinition方法，
 * 			9.7.那么这个方法何时被调用呢？BeanDefinition信息的注册都干了些什么？
 * 			前置步骤	9.7.1 BeanDefinition这个bean定义信息要能进来，就得先读取进来，就先利用BeanDefinitionReader进行读取
 *					9.7.2 也就是说在xml里面定义了一些bean信息（这些都是资源） 然后想办法得读（BeanDefinitionReader）进来，再转为bean定义信息存到档案馆
 *				xml具体流程步骤：
 *					9.7.3 在xml定义了组件，这一个定义就是一个bean的定义信息。
 *					9.7.4 在创建ioc容器（new ApplicationContext）的时候就要进行注册，
 *					9.7.5 那为什么要在创建的时候注册？因为在创建ioc容器（new ApplicationContext）的时候，传了配置文件的位置
 *					9.7.6 从这开始就要从容器中注册bean的定义信息了
 *					9.7.8 先刷新容器refresh(); 所谓的刷新容器是什么呢？
 *					9.7.9 刷新容器的refresh();方法有一个ConfigurableListableBeanFactory这个工厂，这个能帮我们得到到底有多少个bean，bean的定义信息名字等
 *					9.7.10 refreshBeanFactory();也就是说整个spring工厂的整个启动，底层叫刷新容器
 *					9.7.11 在刷新容器的过程中先来创建bean工厂，创建bean工厂的时候
 *					9.7.12 先来创建一个DefaultListableBeanFactory（档案馆） 创建保存所有bean定义信息的档案馆，档案馆里面核心有那些map: beanDefinitionMap
 *					9.7.13 这个档案馆创建好，初始化好以后有一个方法叫loadBeanDefinitions(beanFactory); 也就是加载所有的bean定义信息
 *							也就是xml配置的那些组件（bean定义信息），被加载进去了  如何加载bean定义信息的呢？
 *					9.7.14 loadBeanDefinitions(beanDefinitionReader);	 它利用beanDefinitionReader来加载
 *					9.7.15 beanDefinitionReader这个从XmlBeanDefinitionReader里面来， 它在这里准备了一个beanDefinitionReader，
 *							叫bean定义信息的读取器，也就是读取那些xml内容的读取器
 *					9.7.16 	beanDefinitionReader这个读取器里面还有资源加载器，也就是读取器里面又组合了一个叫资源加载器
 *					9.7.17 	beanDefinitionReader就把资源加载器拿到，拿到以后就loadBeanDefinitions(beanDefinitionReader); 来加载所有的bean的定义信息
 *					如何加载的？
 *					 9.7.18 先获取所有的配置文件的位置（getConfigLocations();）
 *					 9.7.19 然后读取器先来加载所有的bean定义信息reader.loadBeanDefinitions(configLocations); 也就是相当于读取器从这一行开始去读取配置文件了
 *					 读取文件如何读取？
 *					 9.7.20 count += loadBeanDefinitions(location); //挨个加载每一个配置文件里面所有的组件，最后做一个统一的数值，就知道了加载了多少组件
 *					 9.7.21 利用BeanDefinitionDocumentReader去逐个节点进行解析组件
 *					 9.7.22 解析完的信息封装在了BeanDefinitionHolder中
 *					 9.7.23 beanDefinition和beanname这两个玩意要注册到档案馆里面，它就为了方便，就先封装到了这个BeanDefinitionHolder
 *					 9.7.24	然后就再注册这个玩意，直接拿到BeanDefinitionRegistry（bean定义信息的注册中心），给这个注册中心里面利用registerBeanDefinition这个方法进行注册
 *					 如何注册的？
 *					 9.7.25	先来看看这个BeanDefinition对不对，还要对信息进行校验，验证成功以后，再来看这个beanDefinitionMap.get(beanName);里面有没有这个bean的名字
 *					 9.7.26 spring的底层大量使用到了这样的写法，想要给容器里面注册一个定义信息，但是先上来检查beanDefinitionMap里面有没有，没有才进行注册
 *					 9.7.27也就是说现在是逐行解析，解析到每一个bean,解析成了以后，就要把它注册到档案馆（DefaultListableBeanFactory）里面，然后先检查档案馆（beanDefinitionMap）里面有没有
 *					 9.7.28 如果没有就注册进去，如果有就不用注册了
 *
 *					----------------------------------------每一个组件都要经过以上的处理逻辑-----------------------------------
 *
 *					处理完了以后：
 *						BeanDefinitionRegistry  也就是从xml里面解析到的所有东西全部注册到BeanDefinitionRegistry这里面了，
 *					其实是注册到	BeanDefinitionRegistry的map里面
 *
 *					经历了这以上过程，那么档案馆就有当前ioc容器里面所有组件的定义信息
 *					组件的定义信息是什么时候创建的？
 *						1.先传入一个bean的xml文件，这个xml配置文件，根据它来创建ioc容器，ioc容器底层还要刷新容器
 *						2.刷新容器的时候。它得先创建bean的工厂
 *						3.创建bean工厂的时候（也叫刷新工厂）
 *						4.刷新工厂的过程中加载所有的bean定义信息
 *						5，然后就用beanDefinitionReader去读取传入的xml配置文件的内容
 *						6.reader.loadBeanDefinitions(configLocations);  读取指定的配置文件
 *						7.然后读取器挨个遍历每一个指定的配置文件去来解析
 *						8.然后根据传入的xml配置文件的内容	来加载bean的定义信息
 *						9.利用DocumentReader开始读取整篇文档，注册bean的定义信息
 *						10.BeanDefinitionParserDelegate去来读取DocumentReader，也就是解析ocumentReader
 *						11.解析当前标签生成BeanDefinitionHolder
 *
 *						所以它创建bean的定义信息，就是解析出xml配置标签里面的每一个属性，相当于吧xml转为beanDefinition这个java对象
 *						然后直接创建一个GenericBeanDefinition()
 *						然后这个bean定义信息，类名就是xml配置文件指定写的类名
 *						也就是在底层解析每一个标签必须把它的类名得知道，并且类名不为空才有拿，如果为空就返回这个bean定义信息的没类名的
 *
 *						先创建出bean定义信息，然后再解析标签里面的元数据它是先按照类名和id生成一个bean的定义信息
 *
 * 			XXXAware接口是什么时候赋值进来的？(简单了解下spring初始化对象的整个过程)
 *				1.首先追踪IOC容器创建
 *				2.refresh();刷新容器
 *				3.BeanFactory第一次开始创建的时候获取刷新好的bean工厂，
 *				4.完成bean工厂的初始化，所以对象创建是在bean工厂初始化完成的时候干的事
 *				5.初始化里面开始干活,也就是初始化所有的非懒加载的单实例bean，所以接下来bean对象的创建就是在完成bean工厂初始化的时候来初始化所有单实例bean
 *				6.DefaultListableBeanFactory.getBean(beanName);  getBean这个方法是被AbstractBeanFactory bean工厂先定义的  ，这就是模板模式
 *				7.父类AbstractBeanFactory已经做好实现，子类DefaultListableBeanFactory要么调用父类已有的方法，要么就是父类留给一些不实现的东西，子类再实现都可以
 *				8.ioc一启动它优先做的事情就是把档案馆（DefaultListableBeanFactory）里面之前解析xml配置生成的所有bean信息挨个遍历循环来进行获取，想把所有的bean从档案馆里面拿来自己先获取一遍，当然它自己在调用获取的方法是调用的是doGetBean
 *				9.所以DefaultListableBeanFactory.getBean(beanName);  所以会也发现ioc容器一启动的时候，要创建相应写好的对象。还没追踪到创建这个对象，结果上来就会有一个方法叫getBean(beanName);
 *				10.而这个getBean(beanName);还是AbstractBeanFactory bean工厂定义的方法，所以spring默认一上来创建bean的时候它还没先创建，它先是getBean(beanName);
 *				11.spring想从AbstractBeanFactory bean工厂中获取一个bean (getBean(beanName);).因为spring容器一启动就要完成所有单实例的创建，所有单实例的创建都很简单，就是从工厂中获取就完事了
 *				12.所以整个创建逻辑就放在了getBean(beanName)里面，所以这里面有一个doGetBean（执行获取bean的方法）
 *				13.	doGetBean（执行获取bean的方法），先拿到bean的名字，再拿到bean的实例，然后再检查单实例缓存
 *				13.然后缓存所有单实例bean对象，单例对象池，DefaultSingletonBeanRegistry（Bean的注册中心）.singletonObjects，它是一个map
 *				14.也就是说ioc容器底层是所有的单实例对象，以后想要就从singletonObjects这里面拿，这就叫ioc容器，这最起码就是ioc容器的单例池
 *
 *
 *
 * //意思：这是一个根接口，也就是BeanFactory是一个最大的接口，也就是说整个访问容器的入口就是从这进去的
 * The root interface for accessing a Spring bean container.
 *
 * <p>This is the basic client view of a bean container;
 * further interfaces such as {@link ListableBeanFactory} and
 * {@link org.springframework.beans.factory.config.ConfigurableBeanFactory}
 * are available for specific purposes.
 *
 * //意思：这一个接口是一个实现，可以保存很多bean的定义信息
 * <p>This interface is implemented by objects that hold a number of bean definitions,
 *
 * //意思：每一个这个定义信息都有一个唯一的名字
 * each uniquely identified by a String name. Depending on the bean definition,
 *
 * //意思：这个工厂将会返回这个independent（这个就是一个独立的实例）或者也能返回single shared instance（共享的单实例）
 * the factory will return either an independent instance of a contained object
 * (the Prototype design pattern【原型设计模式】), or a single shared instance (a superior
 * alternative to the Singleton design pattern【单例设计模式】, in which the instance is a
 * singleton in the scope of the factory). Which type of instance will be returned
 * depends on the bean factory configuration: the API is the same. Since Spring
 * 2.0, further scopes are available depending on the concrete application
 * context (e.g. "request" and "session" scopes in a web environment).
 *
 * <p>The point of this approach is that the BeanFactory is a central registry
 * of application components, and centralizes configuration of application
 * components (no more do individual objects need to read properties files,
 * for example). See chapters 4 and 11 of "Expert One-on-One J2EE Design and
 * Development" for a discussion of the benefits of this approach.
 *
 * <p>Note that it is generally better to rely on Dependency Injection
 * ("push" configuration) to configure application objects through setters
 * or constructors, rather than use any form of "pull" configuration like a
 * BeanFactory lookup. Spring's Dependency Injection functionality is
 * implemented using this BeanFactory interface and its subinterfaces.
 *
 * <p>Normally a BeanFactory will load bean definitions stored in a configuration
 * source (such as an XML document), and use the {@code org.springframework.beans}
 * package to configure the beans. However, an implementation could simply return
 * Java objects it creates as necessary directly in Java code. There are no
 * constraints on how the definitions could be stored: LDAP, RDBMS, XML,
 * properties file, etc. Implementations are encouraged to support references
 * amongst beans (Dependency Injection).
 *
 * <p>In contrast to the methods in {@link ListableBeanFactory}, all of the
 * operations in this interface will also check parent factories if this is a
 * {@link HierarchicalBeanFactory}. If a bean is not found in this factory instance,
 * the immediate parent factory will be asked. Beans in this factory instance
 * are supposed to override beans of the same name in any parent factory.
 *
 * <p>Bean factory implementations should support the standard bean lifecycle interfaces
 * as far as possible. The full set of initialization methods and their standard order is:
 * <ol>
 * <li>BeanNameAware's {@code setBeanName}
 * <li>BeanClassLoaderAware's {@code setBeanClassLoader}
 * <li>BeanFactoryAware's {@code setBeanFactory}
 * <li>EnvironmentAware's {@code setEnvironment}
 * <li>EmbeddedValueResolverAware's {@code setEmbeddedValueResolver}
 * <li>ResourceLoaderAware's {@code setResourceLoader}
 * (only applicable when running in an application context)
 * <li>ApplicationEventPublisherAware's {@code setApplicationEventPublisher}
 * (only applicable when running in an application context)
 * <li>MessageSourceAware's {@code setMessageSource}
 * (only applicable when running in an application context)
 * <li>ApplicationContextAware's {@code setApplicationContext}
 * (only applicable when running in an application context)
 * <li>ServletContextAware's {@code setServletContext}
 * (only applicable when running in a web application context)
 * <li>{@code postProcessBeforeInitialization} methods of BeanPostProcessors
 * <li>InitializingBean's {@code afterPropertiesSet}
 * <li>a custom init-method definition
 * <li>{@code postProcessAfterInitialization} methods of BeanPostProcessors
 * </ol>
 *
 * <p>On shutdown of a bean factory, the following lifecycle methods apply:
 * <ol>
 * <li>{@code postProcessBeforeDestruction} methods of DestructionAwareBeanPostProcessors
 * <li>DisposableBean's {@code destroy}
 * <li>a custom destroy-method definition
 * </ol>
 *
 * @author Rod Johnson
 * @author Juergen Hoeller
 * @author Chris Beams
 * @since 13 April 2001
 * @see BeanNameAware#setBeanName
 * @see BeanClassLoaderAware#setBeanClassLoader
 * @see BeanFactoryAware#setBeanFactory
 * @see org.springframework.context.ResourceLoaderAware#setResourceLoader
 * @see org.springframework.context.ApplicationEventPublisherAware#setApplicationEventPublisher
 * @see org.springframework.context.MessageSourceAware#setMessageSource
 * @see org.springframework.context.ApplicationContextAware#setApplicationContext
 * @see org.springframework.web.context.ServletContextAware#setServletContext
 * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization
 * @see InitializingBean#afterPropertiesSet
 * @see org.springframework.beans.factory.support.RootBeanDefinition#getInitMethodName
 * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization
 * @see DisposableBean#destroy
 * @see org.springframework.beans.factory.support.RootBeanDefinition#getDestroyMethodName
 */
public interface BeanFactory {

	/**
	 * Used to dereference a {@link FactoryBean} instance and distinguish it from
	 * beans <i>created</i> by the FactoryBean. For example, if the bean named
	 * {@code myJndiObject} is a FactoryBean, getting {@code &myJndiObject}
	 * will return the factory, not the instance returned by the factory.
	 */
	String FACTORY_BEAN_PREFIX = "&";


	/**
	 * Return an instance, which may be shared or independent, of the specified bean.
	 * <p>This method allows a Spring BeanFactory to be used as a replacement for the
	 * Singleton or Prototype design pattern. Callers may retain references to
	 * returned objects in the case of Singleton beans.
	 * <p>Translates aliases back to the corresponding canonical bean name.
	 * <p>Will ask the parent factory if the bean cannot be found in this factory instance.
	 * @param name the name of the bean to retrieve
	 * @return an instance of the bean
	 * @throws NoSuchBeanDefinitionException if there is no bean with the specified name
	 * @throws BeansException if the bean could not be obtained
	 */
	Object getBean(String name) throws BeansException;

	/**
	 * Return an instance, which may be shared or independent, of the specified bean.
	 * <p>Behaves the same as {@link #getBean(String)}, but provides a measure of type
	 * safety by throwing a BeanNotOfRequiredTypeException if the bean is not of the
	 * required type. This means that ClassCastException can't be thrown on casting
	 * the result correctly, as can happen with {@link #getBean(String)}.
	 * <p>Translates aliases back to the corresponding canonical bean name.
	 * <p>Will ask the parent factory if the bean cannot be found in this factory instance.
	 * @param name the name of the bean to retrieve
	 * @param requiredType type the bean must match; can be an interface or superclass
	 * @return an instance of the bean
	 * @throws NoSuchBeanDefinitionException if there is no such bean definition
	 * @throws BeanNotOfRequiredTypeException if the bean is not of the required type
	 * @throws BeansException if the bean could not be created
	 */
	<T> T getBean(String name, Class<T> requiredType) throws BeansException;

	/**
	 * Return an instance, which may be shared or independent, of the specified bean.
	 * <p>Allows for specifying explicit constructor arguments / factory method arguments,
	 * overriding the specified default arguments (if any) in the bean definition.
	 * @param name the name of the bean to retrieve
	 * @param args arguments to use when creating a bean instance using explicit arguments
	 * (only applied when creating a new instance as opposed to retrieving an existing one)
	 * @return an instance of the bean
	 * @throws NoSuchBeanDefinitionException if there is no such bean definition
	 * @throws BeanDefinitionStoreException if arguments have been given but
	 * the affected bean isn't a prototype
	 * @throws BeansException if the bean could not be created
	 * @since 2.5
	 */
	Object getBean(String name, Object... args) throws BeansException;

	/**
	 * Return the bean instance that uniquely matches the given object type, if any.
	 * <p>This method goes into {@link ListableBeanFactory} by-type lookup territory
	 * but may also be translated into a conventional by-name lookup based on the name
	 * of the given type. For more extensive retrieval operations across sets of beans,
	 * use {@link ListableBeanFactory} and/or {@link BeanFactoryUtils}.
	 * @param requiredType type the bean must match; can be an interface or superclass
	 * @return an instance of the single bean matching the required type
	 * @throws NoSuchBeanDefinitionException if no bean of the given type was found
	 * @throws NoUniqueBeanDefinitionException if more than one bean of the given type was found
	 * @throws BeansException if the bean could not be created
	 * @since 3.0
	 * @see ListableBeanFactory
	 */
	<T> T getBean(Class<T> requiredType) throws BeansException;

	/**
	 * Return an instance, which may be shared or independent, of the specified bean.
	 * <p>Allows for specifying explicit constructor arguments / factory method arguments,
	 * overriding the specified default arguments (if any) in the bean definition.
	 * <p>This method goes into {@link ListableBeanFactory} by-type lookup territory
	 * but may also be translated into a conventional by-name lookup based on the name
	 * of the given type. For more extensive retrieval operations across sets of beans,
	 * use {@link ListableBeanFactory} and/or {@link BeanFactoryUtils}.
	 * @param requiredType type the bean must match; can be an interface or superclass
	 * @param args arguments to use when creating a bean instance using explicit arguments
	 * (only applied when creating a new instance as opposed to retrieving an existing one)
	 * @return an instance of the bean
	 * @throws NoSuchBeanDefinitionException if there is no such bean definition
	 * @throws BeanDefinitionStoreException if arguments have been given but
	 * the affected bean isn't a prototype
	 * @throws BeansException if the bean could not be created
	 * @since 4.1
	 */
	<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;

	/**
	 * Return a provider for the specified bean, allowing for lazy on-demand retrieval
	 * of instances, including availability and uniqueness options.
	 * @param requiredType type the bean must match; can be an interface or superclass
	 * @return a corresponding provider handle
	 * @since 5.1
	 * @see #getBeanProvider(ResolvableType)
	 */
	<T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);

	/**
	 * Return a provider for the specified bean, allowing for lazy on-demand retrieval
	 * of instances, including availability and uniqueness options.
	 * @param requiredType type the bean must match; can be a generic type declaration.
	 * Note that collection types are not supported here, in contrast to reflective
	 * injection points. For programmatically retrieving a list of beans matching a
	 * specific type, specify the actual bean type as an argument here and subsequently
	 * use {@link ObjectProvider#orderedStream()} or its lazy streaming/iteration options.
	 * @return a corresponding provider handle
	 * @since 5.1
	 * @see ObjectProvider#iterator()
	 * @see ObjectProvider#stream()
	 * @see ObjectProvider#orderedStream()
	 */
	<T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);

	/**
	 * Does this bean factory contain a bean definition or externally registered singleton
	 * instance with the given name?
	 * <p>If the given name is an alias, it will be translated back to the corresponding
	 * canonical bean name.
	 * <p>If this factory is hierarchical, will ask any parent factory if the bean cannot
	 * be found in this factory instance.
	 * <p>If a bean definition or singleton instance matching the given name is found,
	 * this method will return {@code true} whether the named bean definition is concrete
	 * or abstract, lazy or eager, in scope or not. Therefore, note that a {@code true}
	 * return value from this method does not necessarily indicate that {@link #getBean}
	 * will be able to obtain an instance for the same name.
	 * @param name the name of the bean to query
	 * @return whether a bean with the given name is present
	 */
	boolean containsBean(String name);

	/**
	 * Is this bean a shared singleton? That is, will {@link #getBean} always
	 * return the same instance?
	 * <p>Note: This method returning {@code false} does not clearly indicate
	 * independent instances. It indicates non-singleton instances, which may correspond
	 * to a scoped bean as well. Use the {@link #isPrototype} operation to explicitly
	 * check for independent instances.
	 * <p>Translates aliases back to the corresponding canonical bean name.
	 * <p>Will ask the parent factory if the bean cannot be found in this factory instance.
	 * @param name the name of the bean to query
	 * @return whether this bean corresponds to a singleton instance
	 * @throws NoSuchBeanDefinitionException if there is no bean with the given name
	 * @see #getBean
	 * @see #isPrototype
	 */
	boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

	/**
	 * Is this bean a prototype? That is, will {@link #getBean} always return
	 * independent instances?
	 * <p>Note: This method returning {@code false} does not clearly indicate
	 * a singleton object. It indicates non-independent instances, which may correspond
	 * to a scoped bean as well. Use the {@link #isSingleton} operation to explicitly
	 * check for a shared singleton instance.
	 * <p>Translates aliases back to the corresponding canonical bean name.
	 * <p>Will ask the parent factory if the bean cannot be found in this factory instance.
	 * @param name the name of the bean to query
	 * @return whether this bean will always deliver independent instances
	 * @throws NoSuchBeanDefinitionException if there is no bean with the given name
	 * @since 2.0.3
	 * @see #getBean
	 * @see #isSingleton
	 */
	boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

	/**
	 * Check whether the bean with the given name matches the specified type.
	 * More specifically, check whether a {@link #getBean} call for the given name
	 * would return an object that is assignable to the specified target type.
	 * <p>Translates aliases back to the corresponding canonical bean name.
	 * <p>Will ask the parent factory if the bean cannot be found in this factory instance.
	 * @param name the name of the bean to query
	 * @param typeToMatch the type to match against (as a {@code ResolvableType})
	 * @return {@code true} if the bean type matches,
	 * {@code false} if it doesn't match or cannot be determined yet
	 * @throws NoSuchBeanDefinitionException if there is no bean with the given name
	 * @since 4.2
	 * @see #getBean
	 * @see #getType
	 */
	boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;

	/**
	 * Check whether the bean with the given name matches the specified type.
	 * More specifically, check whether a {@link #getBean} call for the given name
	 * would return an object that is assignable to the specified target type.
	 * <p>Translates aliases back to the corresponding canonical bean name.
	 * <p>Will ask the parent factory if the bean cannot be found in this factory instance.
	 * @param name the name of the bean to query
	 * @param typeToMatch the type to match against (as a {@code Class})
	 * @return {@code true} if the bean type matches,
	 * {@code false} if it doesn't match or cannot be determined yet
	 * @throws NoSuchBeanDefinitionException if there is no bean with the given name
	 * @since 2.0.1
	 * @see #getBean
	 * @see #getType
	 */
	boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;

	/**
	 * Determine the type of the bean with the given name. More specifically,
	 * determine the type of object that {@link #getBean} would return for the given name.
	 * <p>For a {@link FactoryBean}, return the type of object that the FactoryBean creates,
	 * as exposed by {@link FactoryBean#getObjectType()}. This may lead to the initialization
	 * of a previously uninitialized {@code FactoryBean} (see {@link #getType(String, boolean)}).
	 * <p>Translates aliases back to the corresponding canonical bean name.
	 * <p>Will ask the parent factory if the bean cannot be found in this factory instance.
	 * @param name the name of the bean to query
	 * @return the type of the bean, or {@code null} if not determinable
	 * @throws NoSuchBeanDefinitionException if there is no bean with the given name
	 * @since 1.1.2
	 * @see #getBean
	 * @see #isTypeMatch
	 */
	@Nullable
	Class<?> getType(String name) throws NoSuchBeanDefinitionException;

	/**
	 * Determine the type of the bean with the given name. More specifically,
	 * determine the type of object that {@link #getBean} would return for the given name.
	 * <p>For a {@link FactoryBean}, return the type of object that the FactoryBean creates,
	 * as exposed by {@link FactoryBean#getObjectType()}. Depending on the
	 * {@code allowFactoryBeanInit} flag, this may lead to the initialization of a previously
	 * uninitialized {@code FactoryBean} if no early type information is available.
	 * <p>Translates aliases back to the corresponding canonical bean name.
	 * <p>Will ask the parent factory if the bean cannot be found in this factory instance.
	 * @param name the name of the bean to query
	 * @param allowFactoryBeanInit whether a {@code FactoryBean} may get initialized
	 * just for the purpose of determining its object type
	 * @return the type of the bean, or {@code null} if not determinable
	 * @throws NoSuchBeanDefinitionException if there is no bean with the given name
	 * @since 5.2
	 * @see #getBean
	 * @see #isTypeMatch
	 */
	@Nullable
	Class<?> getType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException;

	/**
	 * Return the aliases for the given bean name, if any.
	 * <p>All of those aliases point to the same bean when used in a {@link #getBean} call.
	 * <p>If the given name is an alias, the corresponding original bean name
	 * and other aliases (if any) will be returned, with the original bean name
	 * being the first element in the array.
	 * <p>Will ask the parent factory if the bean cannot be found in this factory instance.
	 * @param name the bean name to check for aliases
	 * @return the aliases, or an empty array if none
	 * @see #getBean
	 */
	String[] getAliases(String name);

}
